﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LL.Business;
using NanoERP.Model.Poco;
using NanoERP.Model.SystemMgmt;
using Omu.ValueInjecter;

namespace NanoERP.Business.Permission
{
    public class ModuleService : ServiceBase
    {
        #region CRUD

        public void AddModule(SYS_Module module)
        {
            var dao = this.DbSession;
            dao.Insert(module);
        }

        public void DeleteModule(Guid moduleId)
        {
            var dao = this.DbSession;
            dao.Delete<SYS_Module>(moduleId);
        }

        public void UpdateModule(SYS_Module module)
        {
            var dao = this.DbSession;
            dao.Update(module);
        }

        public void Move(Guid moduleId, Guid? moduleTypeId)
        {
            var dao = this.DbSession;
            var module = dao.Get<SYS_Module>(moduleId);
            module.TypeId = moduleTypeId;
            dao.Update(module);
        }

        public void AddModuleRight(SYS_Right right)
        {
            var dao = this.DbSession;
            dao.Insert(right);
        }

        public void UpdateModuleRight(SYS_Right right)
        {
            var dao = this.DbSession;
            dao.Update(right);
        }

        public void RemoveModuleRight(Guid moduleRightId)
        {
            var dao = this.DbSession;
            dao.Delete<SYS_Right>(moduleRightId);
        }

        public IList<SYS_Module> GetAllModules()
        {
            return DbSession.GetAll<SYS_Module>();
        }

        #endregion

        public ModuleTree GetModuleTreeByUser(Guid userId)
        {
            var modules = GetModules(userId);
            return BuildModuleTree(modules);
        }

        public ModuleTree GetModuleTreeForUser(Guid userId)
        {
            var modules = GetAllModuleWithUserRights(userId);
            return BuildModuleTree(modules);
        }

        public ModuleTree GetModuleTreeForRole(Guid roleId)
        {
            var modules = GetAllModuleWithRoleRights(roleId);
            return BuildModuleTree(modules);
        }

        private ModuleTree BuildModuleTree(IList<ModuleModel> modules)
        {
            var root = new ModuleTree();
            var types = DbSession.GetAll<SYS_ModuleType>();
            foreach (var moduleType in
                (from d in types where d.ParentId == null orderby d.Sort ascending select d))
            {
                var newItem = new ModuleTree();
                newItem.InjectFrom(moduleType);
                FillSubModuleTree(newItem, types, modules);
                root.Children.Add(newItem);
            }
            foreach (var module in
                (from dd in modules where dd.TypeId == null select dd))
            {
                root.Modules.Add(module);
            }
            return root;
        }

        private void FillSubModuleTree(ModuleTree item, IEnumerable<SYS_ModuleType> types, IEnumerable<ModuleModel> modules)
        {
            var children = from d in types where d.ParentId == item.Id select d;
            foreach (var child in children)
            {
                var newItem = new ModuleTree();
                newItem.InjectFrom(child);
                FillSubModuleTree(newItem, types, modules);
                item.Children.Add(newItem);
            }
            foreach (var module in
                    (from dd in modules where dd.TypeId == item.Id select dd))
            {
                item.Modules.Add(module);
            }
        }

        public IList<ModuleModel> GetAllModuleWithUserRights(Guid userId)
        {
            IList<ModuleModel> list = new List<ModuleModel>();
            var str = new StringBuilder();
            str.AppendLine("SELECT  SYS_Right.* ,");
            str.AppendLine("CONVERT(BIT,CASE WHEN dbo.SYS_Rights_Users.RightId IS NULL ");
            str.AppendLine("THEN 0 ELSE 1 END) Checked");
            str.AppendLine("FROM dbo.SYS_User");
            str.AppendLine("CROSS JOIN dbo.SYS_Right");
            str.AppendLine("LEFT JOIN SYS_Rights_Users ON dbo.SYS_User.Id = dbo.SYS_Rights_Users.UserId");
            str.AppendLine("AND dbo.SYS_Right.Id = dbo.SYS_Rights_Users.RightId");
            str.AppendLine("WHERE dbo.SYS_User.Id=@0");
            var rights = this.DbSession.SqlQuery<RightModel>(str.ToString(), userId);
            IList<SYS_Module> modules = this.GetAllModules();
            foreach (var module in modules)
            {
                var model = new ModuleModel();
                model.InjectFrom(module);
                foreach (var right in
                    (from d in rights where d.ModuleId.Equals(model.Id) select d))
                {
                    model.Rights.Add(right);
                }
                list.Add(model);
            }
            return list;
        }

        public IList<ModuleModel> GetAllModuleWithRoleRights(Guid roleId)
        {
            IList<ModuleModel> list = new List<ModuleModel>();

            var str = new StringBuilder();
            str.AppendLine("SELECT  SYS_Right.* ,");
            str.AppendLine("CONVERT(BIT,CASE WHEN dbo.SYS_Rights_Roles.RightId IS NULL ");
            str.AppendLine("THEN 0 ELSE 1 END) Checked");
            str.AppendLine("FROM dbo.SYS_Role");
            str.AppendLine("CROSS JOIN dbo.SYS_Right");
            str.AppendLine("LEFT JOIN SYS_Rights_Roles ON dbo.SYS_Role.Id = dbo.SYS_Rights_Roles.RoleId");
            str.AppendLine("AND dbo.SYS_Right.Id = dbo.SYS_Rights_Roles.RightId");
            str.AppendLine("WHERE dbo.SYS_Role.Id=@0");
            var rights = this.DbSession.SqlQuery<RightModel>(str.ToString(), roleId);
            IList<SYS_Module> modules = this.GetAllModules();
            foreach (var module in modules)
            {
                var model = new ModuleModel();
                model.InjectFrom(module);
                foreach (var right in
                    (from d in rights where d.ModuleId.Equals(model.Id) select d))
                {
                    model.Rights.Add(right);
                }
                list.Add(model);
            }
            return list;
        }

        public IList<ModuleModel> GetModules(Guid userId)
        {
            var str = new StringBuilder();
            str.AppendLine("SELECT SYS_Module.* FROM dbo.SYS_Module");
            str.AppendLine("INNER JOIN dbo.SYS_Right ON dbo.SYS_Module.Id = dbo.SYS_Right.ModuleId");
            str.AppendLine("INNER JOIN dbo.V_Rights RT ON RT.RightId=dbo.SYS_Right.Id");
            str.AppendLine("WHERE RT.UserId=@0 and dbo.SYS_Right.Code='View' order by SYS_Module.Sort asc");
            var modules = this.DbSession.SqlQuery<SYS_Module>(str.ToString(), userId);

            IList<ModuleModel> list = new List<ModuleModel>();
            foreach (var module in modules)
            {
                var model = new ModuleModel();
                model.InjectFrom(module);
                list.Add(model);
            }
            return list;
        }

        public void SetUserRights(Guid userId, IList<Guid> rights)
        {
            var sqlHelper = this.DbSession;
            sqlHelper.ExcuteNonQuery("delete from SYS_Rights_Users where UserId=@0", userId);
            foreach (Guid right in rights)
            {
                sqlHelper.ExcuteNonQuery("insert into SYS_Rights_Users(UserId,RightId) VALUES(@0,@1)", userId, right);
            }
        }

    }
}
